/**
 * 基础模拟类，用来mock数据
 * Created by wangqian on 2018-07-25 14:07:15.
 * 自动生成
 */
/**
 * 原生的mock，由于adapter不支持delete，只能用原生的
 * @type {MockXMLHttpRequest}
 */
import { formatError, formatRes, MSG_NODATA } from '@/mock.js'

export default class BaseMock {
  /**
   * 初始化基础mock类
   * @param {Number} total 需要的总行数
   * @param {Function} mockFunction 模拟数据的类（会传入index），返回对象
   * @param {Function} filterFunction 过滤函数（传入item即查询参数params，返回true／false）
   * @param {String} subSys 子系统
   * @param {Module} module 模块
   * @param {Mock} Mock mock对象
   * @param {Array} baseItems 基础列表
   * @param {String} primaryFieldName 主键名
   * @returns {Object} class
   */
  constructor (total, mockFunction, filterFunction, subSys, module, Mock, baseItems, primaryFieldName) {
    this.total = total || 10
    if (!mockFunction) {
      throw new Error('mockFunction必须指定')
    }
    if (typeof mockFunction !== 'function') {
      throw new Error('mockFunction必须是函数')
    }
    if (!filterFunction) {
      throw new Error('filterFunction必须指定')
    }
    if (typeof filterFunction !== 'function') {
      throw new Error('filterFunction必须是函数')
    }
    if (!subSys) {
      throw new Error('subSys必须指定（子系统）英文名')
    }
    if (!module) {
      throw new Error('module必须指定（模块）英文名')
    }
    if (!Mock) {
      throw new Error('mock对象不能为null')
    }
    this.Mock = Mock
    let startIndex = 0
    this.items = []
    if (baseItems) {
      this.items = baseItems.concat(this.items)
      startIndex = baseItems.length
    }

    for (let i = startIndex; i < total; i++) {
      let item = mockFunction(i)
      this.items.push(item)
    }
    this.filterFunction = filterFunction
    this.mockFunction = mockFunction
    this.subSys = subSys
    this.module = module
    this.listApi = `${subSys}/${module}`
    this.pageApi = `${subSys}/${module}/page`
    this.getApi = `${subSys}/${module}/[0-9]{1,20}`
    this.findApi = `${subSys}/${module}/find`
    this.createApi = `${subSys}/${module}`
    this.createsApi = `${subSys}/${module}/batch`
    this.updateApi = `${subSys}/${module}/[0-9]{1,20}`
    this.delApi = `${subSys}/${module}/[0-9]{1,20}`
    this.delsApi = `${subSys}/${module}/batch`
    this.primaryFieldName = !primaryFieldName ? 'id' : primaryFieldName
  }

  /**
   *
   * @param {Object} params 参数
   * @return {*} 列表
   */
  list (params) {
    let self = this
    return this.items.filter(item => {
      return self.filterFunction(item, params)
    })
  }

  /**
   * 获取分页数据
   * @param {Object} params 参数
   * @return {{totalRow, data}} 结果集
   */
  getPages (params) {
    let self = this
    var pageList = []
    const {pageIndex = 1, pageSize = 10} = params
    let items = this.items.filter(item => {
      return self.filterFunction(item, params)
    })
    if (items && items.length > 0) {
      pageList = items.filter((item, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1))
    }
    return {
      total: items.length,
      records: pageList
    }
  }

  /**
   * 获取指定记录
   * @param {Number} id 主键id
   * @return {null} 结果
   */
  get (id) {
    let items = this.items.filter((item, index) => {
      return item[this.primaryFieldName] === id || item[this.primaryFieldName].toString() === id
    })
    if (items && items.length > 0) {
      return items[0]
    } else {
      return null
    }
  }

  /**
   * 获取指定记录
   * @param {Object} params 主键id
   * @return {null} 结果
   */
  find (params) {
    let items = this.items
    let key = Object.keys(params)[0]
    if (items && items.length > 0) {
      let ret = items.filter(it => {
        return it[key] === params[key]
      })
      return ret
    } else {
      return null
    }
  }

  /**
   * 创建数据
   * @param {Object} item 对象
   * @return {null|number} 结果
   */
  create (item) {
    item[this.primaryFieldName] = this.items.length + 1 + ''
    item.delStatus = true
    this.items.push(item)
    return item[this.primaryFieldName]
  }

  /**
   * 批量创建数据
   * @param {Object} items 对象
   * @return {null|number} 结果
   */
  creates (items) {
    let ret = []
    let arr = Object.values(items)
    if (!arr) {
      return false
    }
    for (let it of arr) {
      it[this.primaryFieldName] = this.items.length + 1 + ''
      it.delStatus = true
      this.items.push(it)
      ret = [...ret, it[this.primaryFieldName]]
    }
    return ret
  }

  /**
   * 修改数据
   * @param {Object} item 对象
   * @return {true} 结果
   */
  update (item) {
    let index = this.items.findIndex(i => i[this.primaryFieldName] === item[this.primaryFieldName])
    if (index > -1) {
      this.items.splice(index, 1, item)
      return true
    }
    return '未找到对象:' + item[this.primaryFieldName]
  }

  getUrlParaId (baseUrl) {
    let arr = baseUrl.match(/\d+/g)
    return Number.parseInt(arr[arr.length - 1])
  }

  /**
   * 删除单条数据
   * @param {Object} id 对象
   * @return {true} 结果
   */
  del (id) {
    let index = this.items.findIndex(it => it[this.primaryFieldName] === id)
    if (index > -1) {
      this.items.splice(index, 1)
      return true
    }
    return '未找到对象:' + id
  }

  /**
   * 删除多条数据
   * @param {Object} obj 对象
   * @return {true} 结果
   */
  dels (obj) {
    let len = this.items.length
    for (let item of obj.ids) {
      let index = this.items.findIndex(it => it[this.primaryFieldName] === item)
      if (index > -1) {
        this.items.splice(index, 1)
      }
    }
    if (len === this.items.length) {
      return '未找到对象'
    } else {
      return true
    }
  }

  /**
   * 模拟数据集合
   * @returns {Void} 无
   */
  otherMockApi () {
  }

  /**
   * 模拟api
   * @param {Object} Mock mock对象
   * @returns {Void} 无
   */
  mockApi () {
    let self = this

    // 模拟请求列表数据
    self.Mock.onGet(self.listApi).reply(config => {
      return new Promise((resolve, reject) => {
        let itemList = self.list(config.params)
        if (!itemList) {
          reject(formatError(200, MSG_NODATA, self.listApi, 'get'))
          return
        }
        let r = formatRes(itemList)
        resolve([200, r])
      })
    })

    // 模拟分页获取
    self.Mock.onGet(self.pageApi).reply(config => {
      return new Promise((resolve, reject) => {
        let data = self.getPages(config.params)
        if (data) {
          resolve([200, formatRes(data)])
        } else {
          reject(formatError(200, MSG_NODATA, self.pageApi, 'get'))
        }
      })
    })

    // 模拟获取单条记录
    self.Mock.onGet(new RegExp(self.getApi)).reply(config => {
      return new Promise((resolve, reject) => {
        let para = self.getUrlParaId(config.url)
        let data = self.get(para + '')
        if (data) {
          resolve([200, formatRes(data)])
        } else {
          reject(formatError(200, MSG_NODATA, self.getApi, 'get'))
        }
      })
    })

    // 模拟获取单条记录
    self.Mock.onGet(self.findApi).reply(config => {
      return new Promise((resolve, reject) => {
        let data = self.find(config.params)
        if (data) {
          resolve([200, formatRes(data)])
        } else {
          reject(formatError(200, MSG_NODATA, self.findApi, 'get'))
        }
      })
    })

    // 模拟创建单条记录
    self.Mock.onPost(self.createApi).reply(config => {
      return new Promise((resolve, reject) => {
        let rs = self.create(JSON.parse(config.data))
        if (rs) {
          resolve([200, formatRes(rs)])
        } else {
          reject(formatError(200, '新增失败:' + rs))
        }
      })
    })

    // 模拟创建多条记录
    self.Mock.onPost(self.createsApi).reply(config => {
      return new Promise((resolve, reject) => {
        let rs = self.creates(JSON.parse(config.data))
        if (rs) {
          resolve([200, formatRes(rs)])
        } else {
          reject(formatError(200, '新增失败:' + rs))
        }
      })
    })

    // 模拟修改单条记录
    self.Mock.onPut(new RegExp(self.updateApi)).reply(config => {
      return new Promise((resolve, reject) => {
        let rs = self.update(JSON.parse(config.data))
        if (rs && typeof rs === 'boolean') {
          resolve([200, formatRes(rs)])
        } else {
          reject(formatError(200, '修改失败:' + rs))
        }
      })
    })

    // 模拟删除单条记录
    self.Mock.onDelete(new RegExp(self.delApi)).reply(config => {
      return new Promise((resolve, reject) => {
        let para = self.getUrlParaId(config.url) + ''
        let rs = self.del(para)
        if (rs && typeof rs === 'boolean') {
          resolve([200, formatRes(rs)])
        } else {
          reject(formatError(200, '删除失败:' + rs))
        }
      })
    })

    // 模拟删除多条记录
    self.Mock.onDelete(self.delsApi).reply(config => {
      return new Promise((resolve, reject) => {
        let rs = self.dels(config.params)
        if (rs && typeof rs === 'boolean') {
          resolve([200, formatRes(rs)])
        } else {
          reject(formatError(200, '删除失败:' + rs))
        }
      })
    })
    self.otherMockApi()
  }
}
